package com.demomaster.quickaccessibility.service;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;

import com.demomaster.quickaccessibility.cache.AccessNodeCache;
import com.demomaster.quickaccessibility.core.QuickAccessibility;
import com.demomaster.quickaccessibility.model.QuickAccessibilityNodeInfo;
import com.demomaster.quickcompat.util.DisplayUtil;
import com.demomaster.quickcompat.util.QuickHandler;

import java.util.HashMap;
import java.util.Map;

public class QuickAccessibilityService extends AccessibilityService {
    public static final String TAG = QuickAccessibilityService.class.getSimpleName();
    public static QuickAccessibilityService instance;
    Map<String, String> packageWithActivityMap;
    public int screenWidth;
    public int screenHeight;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        mHandler = new MyHandler();
        screenWidth = DisplayUtil.getScreenWidth(getApplicationContext());
        screenHeight = DisplayUtil.getScreenHeight(getApplicationContext());
        packageWithActivityMap = new HashMap<>();
        QuickAccessibility.getInstance().serviceLifecycleNotifier.onServiceCreate(instance);
    }

    //初始化
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d(TAG, "无障碍服务【开启】");

        AccessibilityServiceInfo serviceInfo = getServiceInfo();
        if (serviceInfo == null) {
            serviceInfo = new AccessibilityServiceInfo();
        }
        serviceInfo.notificationTimeout = 3000;
        setServiceInfo(serviceInfo);
        QuickAccessibility.getInstance().serviceLifecycleNotifier.onServiceCreate(instance);
    }

    String lastActivity;
    String currentActivityName;
    String currentPackageName;

    QuickAccessibilityNodeInfo quickAccessNodeInfo;

    public QuickAccessibilityNodeInfo getQuickAccessNodeInfo() {
        AccessibilityNodeInfo mRootNodeInfo = super.getRootInActiveWindow();
        if (mRootNodeInfo != null) {
            if (quickAccessNodeInfo == null) {
                quickAccessNodeInfo = new QuickAccessibilityNodeInfo(mRootNodeInfo);
            } else {
                quickAccessNodeInfo.setNode(mRootNodeInfo);
            }
        }
        return quickAccessNodeInfo;
    }

    @Override
    public AccessibilityNodeInfo getRootInActiveWindow() {
        if (mRootNodeInfo == null || hasNewEvent) {
            mRootNodeInfo = super.getRootInActiveWindow();
            lastGetRootNodeTime = System.currentTimeMillis();
            hasNewEvent = false;
            return mRootNodeInfo;
        } else {
            if (System.currentTimeMillis() - lastGetRootNodeTime > 3000) {
                mRootNodeInfo = super.getRootInActiveWindow();
                lastGetRootNodeTime = System.currentTimeMillis();
                hasNewEvent = false;
                return mRootNodeInfo;
            }
        }
        //AccessibilityNodeInfo accessibilityNodeInfo =  super.getRootInActiveWindow();
        return mRootNodeInfo;
    }

    AccessibilityNodeInfo mRootNodeInfo;
    long lastGetRootNodeTime;
    boolean hasNewEvent;

    //实现辅助功能
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (!QuickAccessibility.getInstance().isScreenOn) {
            return;
        }
        int eventType = event.getEventType();
        lastEvent = event;
        hasNewEvent = true;
        //Log.e(TAG, "eventType22=" + Integer.toHexString(eventType));
        AccessNodeCache.getInstance().update(event);
        if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED
                || eventType == AccessibilityEvent.TYPE_GESTURE_DETECTION_START
                || eventType == AccessibilityEvent.TYPE_GESTURE_DETECTION_END
                || eventType == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
                || eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
                || eventType == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {//忽略这些类型的事件
            return;
        }
        String currentPackageNameNew = currentPackageName;
        String currentActivityNameNew = currentActivityName;
        updatePackageAndActivity(event);
        if (currentPackageName == null
                || !currentPackageName.equals(currentPackageNameNew)
                || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                || eventType == AccessibilityEvent.TYPE_WINDOWS_CHANGED
                || (currentActivityNameNew != null && !currentActivityNameNew.equals(currentActivityName))
                || (currentActivityName != null && !currentActivityName.equals(currentActivityNameNew))) {
            mHandler.post(delayRunnable, event);
            return;
        }
        //if (eventType == TYPE_WINDOW_CONTENT_CHANGED || eventType == TYPE_WINDOWS_CHANGED) {
        if (!mHandler.hasCallbacks2(delayRunnable)) {
            if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
                mHandler.postDelayed3(delayRunnable, 5000, event);
            } else {
                mHandler.postDelayed3(delayRunnable, 200, event);
            }
            //Log.e(TAG, "eventType2=" + Integer.toHexString(eventType)+",用时2：" + (System.currentTimeMillis() - time1));
        } else {
            if (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && mHandler.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
                mHandler.removeCallbacks2(delayRunnable);
                mHandler.postDelayed3(delayRunnable, 200, event);
            }else {
                if(eventType!=AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
                    Log.d(TAG, "无处理=" + Integer.toHexString(eventType) + ",source=" + event.getSource());
                }
            }
        }
        //}
    }

    private void updatePackageAndActivity(AccessibilityEvent event) {
        int eventType = event.getEventType();
        String packageName1 = null;
        String activityName1 = null;
        switch (eventType) {
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                //case TYPE_WINDOWS_CHANGED:
                //Log.d(TAG, "窗口信息，当前包名:" + currentPackageName + ",页面:" + QuickAccessibility.getInstance().getCurrentActivityName());
                AccessibilityNodeInfo rootNode = getRootInActiveWindow();
                if (rootNode != null) {
                    //Log.d(TAG, "TYPE_WINDOW_STATE_CHANGED_0:" + event.getWindowId() + "]" + event.getPackageName() + "<===>" + event.getClassName() + ",root=" + accessibilityNodeInfo.getWindowId() + "]" + accessibilityNodeInfo.getPackageName() + ",act=" + accessibilityNodeInfo.getClassName());
                    if (!TextUtils.isEmpty(event.getPackageName()) && event.getPackageName().equals(rootNode.getPackageName())) {
                        packageName1 = rootNode.getPackageName().toString();
                        activityName1 = event.getClassName().toString();
                    }
                } else {
                    packageName1 = event.getPackageName().toString();
                    activityName1 = event.getClassName().toString();
                    //Log.d(TAG, "TYPE_WINDOW_STATE_CHANGED_3:" + event.getWindowId() + "]" + event.getPackageName() + "<===>" + event.getClassName());
                }
                updateCurrentPackage(packageName1);
                updateCurrentActivity(packageName1, activityName1);
                break;
            default:
                //if (eventType != CONTENT_CHANGE_TYPE_ERROR) {
                AccessibilityNodeInfo rootNode2 = getRootInActiveWindow();
                if (rootNode2 != null && !TextUtils.isEmpty(rootNode2.getPackageName())) {
                    //updateCurrentPackage(rootNode2.getPackageName().toString());
                    String packageNameT = rootNode2.getPackageName().toString();
                    if (!TextUtils.isEmpty(packageNameT)) {
                        if (!packageNameT.equals(currentPackageName)) {
                            updateCurrentPackage(packageNameT);
                            currentActivityName = null;
                            //Log.d(TAG, "TYPE_WINDOW_STATE_CHANGED_0:" + event.getWindowId() + "]" + event.getPackageName() + "<===>" + event.getClassName() + ",root=" + accessibilityNodeInfo.getWindowId() + "]" + accessibilityNodeInfo.getPackageName() + ",act=" + accessibilityNodeInfo.getClassName());
                            if (!TextUtils.isEmpty(event.getPackageName()) && event.getPackageName().equals(packageNameT) && !TextUtils.isEmpty(event.getClassName())) {
                                activityName1 = event.getClassName().toString();
                            }
                            Log.i(TAG, "包名变更：" + packageNameT + ",页面：" + currentActivityName + ",activityName1=" + activityName1);
                            if (TextUtils.isEmpty(activityName1) && !TextUtils.isEmpty(event.getClassName())) {
                                activityName1 = event.getClassName().toString();
                                Log.e(TAG, "activityName1为空，使用event.getClassName()：" + activityName1);
                            }
                        }
                    }
                }
//                else {
//                    if (!TextUtils.isEmpty(event.getClassName())) {
//                        activityName1 = event.getClassName().toString();
//                        Log.e(TAG, "activityName11111=" + activityName1);
//                    }
//                }
                //}
                break;
        }
    }

    AccessibilityEvent lastEvent;
    MyHandler mHandler;
    Runnable delayRunnable = new Runnable() {
        @Override
        public void run() {
            if (lastEvent != null) {
                QuickAccessibility.getInstance().serviceLifecycleNotifier.onAccessibilityEvent(lastEvent);
            }
            mHandler.removeCallbacks2(this);
        }
    };

    /**
     * 模拟全局按键 performGlobalAction "Android 4.1及以上系统才支持此功能
     */
    @Override
    public void onInterrupt() {
        Log.d(TAG, "辅助功能被迫中断");
    }

    @Override
    public void onDestroy() {
        QuickAccessibility.getInstance().serviceLifecycleNotifier.onServiceDestroy();
        instance = null;
        super.onDestroy();
        Log.i(TAG, "辅助功能已关闭");
    }

    //跳转系统自带界面 辅助功能界面
    public static void startSettintActivity(Context context) {
        /*Intent intent = new Intent(context, DialogWindowActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("permission", Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
        intent.putExtras(bundle);
        (context).startActivity(intent);*/
        //TODO QuickPermission.with().permissions(Manifest.permission.BIND_ACCESSIBILITY_SERVICE).request();
    }

    /*********************/

    public AccessibilityWindowInfo getWindowById(int id) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            for (AccessibilityWindowInfo windowInfo : getWindows()) {
                if (windowInfo.getId() == id) {
                    return windowInfo;
                }
            }
        }
        return null;
    }

    public AccessibilityWindowInfo getTopWindow() {
        AccessibilityWindowInfo topWindowInfo = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            for (AccessibilityWindowInfo windowInfo : getWindows()) {
                if (topWindowInfo == null) {
                    topWindowInfo = windowInfo;
                } else {
                    if (topWindowInfo.getLayer() < windowInfo.getLayer()) {
                        topWindowInfo = windowInfo;
                    }
                }
                //QdLog.println("windowInfo=" + windowInfo.toString());
            }
        }
        return topWindowInfo;
    }

    /**
     * 添加要监听的包名
     *
     * @param packageName
     */
    public static void addPackage(String packageName) {
        packageMap.put(packageName, "");
        resetPackage();
    }

    /**
     * 重置服务包名（需要服务启动时执行）
     */
    public static void resetPackage() {
        if (instance != null) {
            AccessibilityServiceInfo serviceInfo = instance.getServiceInfo();
            if (serviceInfo != null) {
                if (serviceInfo.packageNames != null) {
                    for (String packageName : serviceInfo.packageNames) {
                        packageMap.put(packageName, packageName);
                    }
                }
                String[] arr = new String[packageMap.size()];
                int i = 0;
                for (Map.Entry entry : packageMap.entrySet()) {
                    arr[i] = (String) entry.getKey();
                    i++;
                }
                serviceInfo.packageNames = arr;
                serviceInfo.notificationTimeout = 3000;
                instance.setServiceInfo(serviceInfo);
            }
        }
    }

    public static final Map<String, String> packageMap = new HashMap<>();

    public void performGlobalAction(AccessibilityAction eventMessage) {
        if (eventMessage != null) {
            performGlobalAction(eventMessage.action);
        }
    }

    public boolean updateCurrentPackage(String packageName) {
        if (!TextUtils.isEmpty(packageName)) {
            if (!packageName.equals(currentPackageName)) {
                currentPackageName = packageName;
                Log.i(TAG, "包名更新：" + packageName);
                return true;
            }
        }
        return false;
    }

    public boolean updateCurrentActivity(String packageName, String activityName) {
        //Log.d(TAG, "activityName7=" + activityName);
        if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(activityName) && !activityName.equals(currentActivityName)) {
            if (isActivityExists(packageName, activityName)) {
                lastActivity = currentActivityName;
                currentActivityName = activityName;
                packageWithActivityMap.put(packageName, activityName);
                Log.d(TAG, "页面更新，包名:" + packageName + ",页面:" + currentActivityName + ",上一页面：" + lastActivity);
                return true;
            }
        }
        return false;
    }


    private boolean isActivityExists(String packageName, String activityName) {
        if (isPackageExists(packageName)) {
            try {
                ComponentName componentName = new ComponentName(
                        packageName,
                        activityName
                );
                ActivityInfo activityInfo = getPackageManager().getActivityInfo(componentName, 0);
                if (activityInfo != null) {
                    return true;
                }
            } catch (PackageManager.NameNotFoundException e) {

            }
        }
        return false;
    }

    private boolean isPackageExists(String packageName) {
        try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(packageName, 0);
            if (packageInfo != null) {
                return true;
            }
        } catch (PackageManager.NameNotFoundException e) {

        }
        return false;
    }

    public String getCurrentActivityName() {
        if (TextUtils.isEmpty(currentActivityName) && !TextUtils.isEmpty(currentPackageName)) {
            if (packageWithActivityMap.containsKey(currentPackageName)) {
                currentActivityName = packageWithActivityMap.get(currentPackageName);
                Log.d(TAG, "更新页面信息2，包名:" + currentPackageName + ",页面:" + currentActivityName);
            }
        }
        return currentActivityName;
    }

    public String getCurrentPackageName() {
        return currentPackageName;
    }

    public static class MyHandler extends QuickHandler {

        int eventType;

        public void postDelayed3(Runnable r, long delayMillis, AccessibilityEvent event) {
            eventType = event.getEventType();
            super.postDelayed2(r, delayMillis);
        }

        public void post(Runnable delayRunnable, AccessibilityEvent event) {
            eventType = event.getEventType();
            super.post(delayRunnable);
        }
    }
}
